package com.gome.boot.config.web.controller;

import com.gome.boot.common.logger.BaseLogger;
import com.gome.boot.common.util.CommonUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 基础Web控制器.
 *
 * @author baoxiufeng
 */
public class BaseController extends BaseLogger {
    private static final String UNKNOWN = "unknown";
    private static final String LOCAL_ADDR = "0:0:0:0:0:0:0:1";

    private String jsonpFunctionParam = "callback";

    private boolean requestParamEmptyAsNull = true;

    public ApplicationContext getApplicationContext() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return RequestContextUtils.findWebApplicationContext(request);
    }

    public <T> T getBean(String name, Class<T> requiredType) {
        return this.getApplicationContext().getBean(name, requiredType);
    }

    public <T> T getBean(Class<T> requiredType) {
        return this.getApplicationContext().getBean(requiredType);
    }

    public HttpServletRequest getRequest() {
        MultipartResolver multipartResolver = null;
        try {
            multipartResolver = this.getApplicationContext().getBean(MultipartResolver.class);
        } catch (NoSuchBeanDefinitionException e) {
            ;
        }
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return (multipartResolver != null && multipartResolver.isMultipart(request) ? multipartResolver.resolveMultipart(request) : request);
    }

    /**
     * 取WAP客户端IP.
     *
     * @param request 客户端请求
     * @return 客户端IP
     */
    protected String getIpAddr(HttpServletRequest request) {
        if (request == null) {
            request = getRequest();
        }
        String ip = request.getHeader("x-forwarded-for");
        if (CommonUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (CommonUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (CommonUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (CommonUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (CommonUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (CommonUtils.isNotEmpty(ip)) {
            String[] ipArr = ip.split(" |,");
            if (ipArr.length > 0) {
                ip = ipArr[0];
            }
        }
        if (LOCAL_ADDR.equals(ip)) {
            ip = "127.0.0.1";
        }
        return ip;
    }

    public String getParameter(String name) {
        String p = this.getRequest().getParameter(name);
        return p == null ? null : (this.requestParamEmptyAsNull && CommonUtils.isEmpty(p) ? null : p.trim());
    }

    public Object jsonp(Object data, String jsonpFunction) {
        MappingJacksonValue value = new MappingJacksonValue(data);
        value.setJsonpFunction(jsonpFunction);
        return value;
    }

    public Object jsonp(Object data) {
        String jsonpFunction = this.getParameter(this.getJsonpFunctionParam());
        return this.isValidJsonpFunction(jsonpFunction) ? this.jsonp(data, jsonpFunction) : data;
    }

    public void noCache(HttpServletResponse response) {
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Cache-Control", "no-store");
        response.setHeader("Pragma", "no-cache");
        response.setDateHeader("Expires", -1L);
    }

    public String getJsonpFunctionParam() {
        return this.jsonpFunctionParam;
    }

    private boolean isValidJsonpFunction(String jsonpFunction) {
        return CommonUtils.isNotEmpty(jsonpFunction) && jsonpFunction.matches("[a-zA-Z0-9_-]+");
    }
}
